package com.lemo.smart.core;

import com.lemo.smart.bean.Data;
import com.lemo.smart.bean.Handler;
import com.lemo.smart.bean.Param;
import com.lemo.smart.bean.View;
import com.lemo.smart.helper.BeanHelper;
import com.lemo.smart.helper.ConfigHelper;
import com.lemo.smart.helper.ControllerHelper;
import com.lemo.smart.helper.HelperLoader;
import com.lemo.smart.helper.ServletHelper;
import com.lemo.smart.util.ArrayUtil;
import com.lemo.smart.util.CodecUtil;
import com.lemo.smart.util.JsonUtil;
import com.lemo.smart.util.ReflectionUtil;
import com.lemo.smart.util.StreamUtil;
import com.lemo.smart.util.StringUtil;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 请求转发器
 * Created by 罗选通 on 2017/12/22.
 */
public class DispatcherServlet extends HttpServlet {
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletHelper.init(req, resp);
    try {
      //获取请求方法和请求路径
      String requestMethod = req.getMethod().toLowerCase();
      String requestPath = req.getPathInfo();
      //获取action处理器
      Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
      if (handler != null) {
        //获取controller类及bean实例
        Class<?> controllerClass = handler.getControllerClass();
        Object controllerBean = BeanHelper.getBean(controllerClass);
        //创建请求参数对象
        Map<String, Object> paramMap = new HashMap<String, Object>();
        Enumeration<String> parameterNames = req.getParameterNames();
        while (parameterNames.hasMoreElements()) {
          String key = parameterNames.nextElement();
          String paramValue = req.getParameter(key);
          paramMap.put(key, paramValue);
        }
        String body = CodecUtil.decodeURL(StreamUtil.getString(req.getInputStream()));
        if (StringUtils.isNotBlank(body)) {
          String[] params = StringUtil.splitString(body, "&");
          if (!ArrayUtils.isEmpty(params)) {
            for (String param : params) {
              String[] array = StringUtil.splitString(param, "=");
              if (ArrayUtil.isNotEmpty(array) && array.length == 2) {
                String paramName = array[0];
                String paramValue = array[1];
                paramMap.put(paramName, paramValue);
              }
            }
          }
        }
        Param param = new Param(paramMap);
        Method actionMethod = handler.getActionMethod();
        Object result;
        if (param.isEmpty()) {
          result = ReflectionUtil.invokeMethod(controllerBean, actionMethod);
        } else {
          result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
        }
        //处理action方法返回值
        if (result instanceof View) {
          //返回jsp页面
          View view = (View) result;
          String path = view.getPath();
          if (StringUtils.isNotBlank(path)) {
            if (path.startsWith("/")) {
              resp.sendRedirect(req.getContextPath() + path);
            } else {
              Map<String, Object> model = view.getModel();
              for (Map.Entry<String, Object> entry : model.entrySet()) {
                req.setAttribute(entry.getKey(), entry.getValue());
              }
              req.setCharacterEncoding("utf-8");
              resp.setContentType("text/html;charset=utf-8");
              req.getRequestDispatcher(ConfigHelper.getJspPath() + path).forward(req, resp);
            }
          }
        } else if (result instanceof Data) {
          //返回json数据
          Data data = (Data) result;
          Object model = data.getModel();
          if (model != null) {
            resp.setContentType("application/json");
            resp.setCharacterEncoding("utf-8");
            PrintWriter writer = resp.getWriter();
            writer.write(JsonUtil.toJSON(model));
            writer.flush();
            writer.close();
          }
        }
      }
    } finally {
      ServletHelper.destroy();
    }
  }

  @Override
  public void init(ServletConfig config) throws ServletException {
    //初始化相关helper类
    HelperLoader.init();
    //获取ServletContext对象(用于注册servlet)
    ServletContext servletContext = config.getServletContext();
    //注册处理jsp的servlet
    ServletRegistration jsp = servletContext.getServletRegistration("jsp");
    jsp.addMapping(ConfigHelper.getJspPath() + "*");
    //注册处理静态资源的servlet
    ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
    defaultServlet.addMapping(ConfigHelper.getAssetPath() + "*");
  }
}
